package com.inspur.edp.bef.bemanager.codegenerator.actions;


import com.inspur.edp.bef.bemanager.codegenerator.JavaCompCodeNames;
import com.inspur.edp.bef.bemanager.codegenerator.ParameterInfo;
import com.inspur.edp.bef.bemanager.util.CheckInfoUtil;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityErrorCodeEnum;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityException;
import com.inspur.edp.bef.bizentity.operation.BizActionBase;
import com.inspur.edp.bef.bizentity.operation.BizOperation;
import com.inspur.edp.bef.bizentity.operation.componentbase.BizParameter;
import com.inspur.edp.bef.bizentity.operation.componentbase.BizVoidReturnType;
import com.inspur.edp.bef.bizentity.operation.componentenum.BizCollectionParameterType;
import com.inspur.edp.bef.bizentity.operation.componentenum.BizParameterType;
import com.inspur.edp.bef.bizentity.operation.componentinterface.IBizParameter;

import java.util.Map;

public abstract class JavaBaseActionGenerator extends JavaBaseCompCodeGenerator {

    ///#region 字段和属性
    private BizActionBase action;
    private java.util.ArrayList<String> usingList;
    private java.util.LinkedHashMap<String, ParameterInfo> parameters;
    private java.util.ArrayList<Class> allGenericParamType;
    protected String ReturnTypeName = "VoidActionResult";

    ///#endregion


    ///#region 构造与初始化
    public JavaBaseActionGenerator(GspBusinessEntity be, BizOperation operation, String nameSpace, String path) {
        super(be, operation, nameSpace, path);
        action = (BizActionBase) ((operation instanceof BizActionBase) ? operation : null);
        if (action == null) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0043);
        }
        usingList = new java.util.ArrayList<String>();
        allGenericParamType = new java.util.ArrayList<Class>();


        ///#region ReturnValue
        if (action.getReturnValue() != null && !(action.getReturnValue() instanceof BizVoidReturnType)) {
            JavaGetParameterUsing(action.getReturnValue());
            ReturnTypeName = JavaGetParameterTypeName(action.getReturnValue());
        }

        ///#endregion


        ///#region Parameters
        if (action.getParameters() == null || action.getParameters().getCount() < 1) {
            return;
        }
        parameters = new java.util.LinkedHashMap<String, ParameterInfo>();

        for (Object actionParameter : action.getParameters()) {
            JavaGetParameterUsing((IBizParameter) actionParameter);
            if (parameters.containsKey(((IBizParameter) actionParameter).getParamCode())) {
                throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0044, ((IBizParameter) actionParameter).getParamCode());
            }
            parameters.put(((IBizParameter) actionParameter).getParamCode(), JavaBuildParameterInfo((IBizParameter) actionParameter));
        }

        ///#endregion
    }

    private void JavaGetParameterUsing(IBizParameter param) {
        if (param.getCollectionParameterType() == BizCollectionParameterType.List) {
            JavaAddUsing(JavaCompCodeNames.ArrayListNameSpace);
        }
        if (param.getParameterType() == BizParameterType.DateTime) {
            JavaAddUsing(JavaCompCodeNames.DateNameSpace);
        }
        if (param.getParameterType() == BizParameterType.Decimal) {
            JavaAddUsing(JavaCompCodeNames.BigDecimalNameSpace);
        }
        if (param.getParameterType() == BizParameterType.Custom) {
            JavaAddUsing(param.getClassName());
        }

    }

    private String JavaGetParameterTypeName(IBizParameter param) {
        switch (param.getCollectionParameterType()) {
            case None:
                return GetNoneCollectionParaTypeName(param);
            case List:
                return GetListParaTypeName(param);
            case Array:
                return GetArrayParaTypeName(param);
            default:
                throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0045, param.getParamName());
        }


    }

    private String GetNoneCollectionParaTypeName(IBizParameter param) {

        switch (param.getParameterType()) {
            case String:
                return "String";
            case Boolean:
                return "Boolean";
            case DateTime:
                return "Date";
            case Decimal:
                return "BigDecimal";
            case Double:
                return "Double";
            case Int32:
                return "Integer";
            case Object:
                return "Object";
            default:
                HandleJavaInfo(param);
                if (CheckInfoUtil.checkNull(param.getClassName())) {
                    throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0046, param.getParamName());
                }
                int index = param.getClassName().lastIndexOf(".");
                return param.getClassName().substring(index + 1, param.getClassName().length());

//				if (!JavaIsGeneric(param))
//				{
//					return param.getClassName().substring(index + 1, index + 1 + param.getClassName().length() - index - 1);
//				}
//				else
//				{
//					String result = JavaGetGenericExpress(allGenericParamType.get(0));
//					allGenericParamType.clear();
//					return result;
//				}

        }
    }

    private String GetArrayParaTypeName(IBizParameter param) {
        switch (param.getParameterType()) {
            case String:
                return "String[]";
            case Boolean:
                return "Boolean[]";
            case DateTime:
                return "Date[]";
            case Decimal:
                return "BigDecimal[]";
            case Double:
                return "Double[]";
            case Int32:
                return "Integer[]";
            case Object:
                return "Object[]";
            default:
                HandleJavaInfo(param);
                if (CheckInfoUtil.checkNull(param.getClassName())) {
                    throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0046, param.getParamName());
                }


                int index = param.getClassName().lastIndexOf(".");
                return param.getClassName().substring(index + 1, param.getClassName().length()) + "[]";

//				int index = param.getClassName().lastIndexOf(".", StringComparison.Ordinal);
//				if (!JavaIsGeneric(param))
//				{
//					return param.getClassName().substring(index + 1, index + 1 + param.getClassName().length() - index - 1) + "[]";
//				}
//				else
//				{
//					String result = JavaGetGenericExpress(allGenericParamType.get(0));
//					allGenericParamType.clear();
//					return result + "[]";
//				}

        }
    }

    private String GetListParaTypeName(IBizParameter param) {
        switch (param.getParameterType()) {
            case String:
                return "ArrayList<String>";
            case Boolean:
                return "ArrayList<Boolean>";
            case DateTime:
                return "ArrayList<Date>";
            case Decimal:
                return "ArrayList<BigDecimal>";
            case Double:
                return "ArrayList<Double>";
            case Int32:
                return "ArrayList<Integer>";
            case Object:
                return "ArrayList<Object>";
            default:
                HandleJavaInfo(param);
                if (CheckInfoUtil.checkNull(param.getClassName())) {
                    throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0046, param.getParamName());
                }
                int index = param.getClassName().lastIndexOf(".");
                return "ArrayList<" + param.getClassName().substring(index + 1, param.getClassName().length()) + ">";

//				if (!JavaIsGeneric(param))
//				{
//					return "ArrayList<" + param.getClassName().substring(index + 1, index + 1 + param.getClassName().length() - index - 1) + ">";
//				}
//				else
//				{
//					String result = JavaGetGenericExpress(allGenericParamType.get(0));
//					allGenericParamType.clear();
//					return "ArrayList<" + result + ">";
//				}

        }
    }

    private String JavaGetParameterMode(IBizParameter param) {
        switch (param.getMode()) {
            case OUT:
                return "out";
            //TODO 待确认
            case INOUT:
                return "ref";
            default:
                return "";
        }

    }

    private ParameterInfo JavaBuildParameterInfo(IBizParameter param) {
        String typeName = JavaGetParameterTypeName(param);
        String paramMode = JavaGetParameterMode(param);
        ParameterInfo tempVar = new ParameterInfo();
        tempVar.setParamName(param.getParamCode());
        tempVar.setParamType(typeName);
        tempVar.setParameterMode(paramMode);
        return tempVar;
    }

    ///#endregion


    ///#region Using
    @Override
    protected void JavaGenerateExtendUsing(StringBuilder result) {
        result.append(GetImportStr(JavaCompCodeNames.ActionApiNameSpace));
        result.append(GetImportStr(JavaCompCodeNames.BaseNameSpace));
        result.append(GetImportStr(JavaCompCodeNames.ChangesetNameSpace));
        result.append(GetImportStr(JavaCompCodeNames.ContextNameSpace));
        result.append(GetImportStr(JavaCompCodeNames.VoidActionResultNameSpace));

        if (getBaseClassName().contains("bstractManagerAction")) {
            result.append(GetImportStr(JavaCompCodeNames.AbstractManagerActionNameSpace));
        }
        if (getBaseClassName().contains("RootAbstractAction")) {
            result.append(GetImportStr(JavaCompCodeNames.RootAbstractActionNameSpaceNameSpace));
        }
        //参数列表
        if (usingList == null || usingList.size() < 1) {
            return;
        }
        for (String usingName : usingList) {
            result.append(GetImportStr(usingName));
        }
    }

    protected boolean JavaHasCustomConstructorParams() {
        if (parameters == null || parameters.size() < 1) {
            return false;
        }
        return true;
    }

    protected void JavaGenerateConstructorParams(StringBuilder result) {

        for (int i = 0; i < parameters.size(); i++) {

            String parameterKey = (String) parameters.keySet().toArray()[i];

            ParameterInfo parameterValue = parameters.get(parameterKey);
            result.append(" ");
            if (!CheckInfoUtil.checkNull(parameterValue.getParameterMode())) {
                result.append(parameterValue.getParameterMode()).append(" ");
            }
            result.append(parameterValue.getParamType()).append(" ").append(parameterKey);
            if (i < parameters.size() - 1) {
                result.append(",");
            }

        }
    }

    protected void JavaGenerateConstructorContent(StringBuilder result) {
        if (parameters == null || parameters.size() < 1) {
            return;
        }

        for (Map.Entry<String, ParameterInfo> parameter : parameters.entrySet()) {
            result.append(GetIndentationStr()).append(GetIndentationStr()).append("this.").append(parameter.getKey()).append(" = ").append(parameter.getKey()).append(";").append(getNewline());

        }
    }


    ///#region Field
    @Override
    protected void JavaGenerateField(StringBuilder result) {
        if (parameters == null || parameters.size() < 1) {
            return;
        }

        for (Map.Entry<String, ParameterInfo> parameter : parameters.entrySet()) {
            result.append(getNewline()).append(GetIndentationStr()).append(JavaCompCodeNames.KeywordPrivate).append(" ").append(parameter.getValue().getParamType()).append(" ").append(parameter.getKey()).append(";");

        }
    }

    ///#endregion

    private boolean JavaIsGeneric(IBizParameter param) {
        try {

//			var psn = Assembly.Load(param.getAssembly());
//			Class type = psn.GetType(param.getJavaClassName());
//			return type.IsGenericType;
            return true;
        } catch (Exception e) {
            //如果libs目录下如果未加载到程序集，默认其不是泛型类型
            return false;
        }


    }

    //把泛型参数类型涉及到的所有类型得到并存在List集合中
    private void JavaGetAllGenericParameterType(Class type) {
//		if (allGenericParamType.isEmpty())
//		{
//			allGenericParamType.add(type);
//		}
//		Class[] allType = type.GetGenericArguments();
//
//		for (Class t : allType)
//		{
//			allGenericParamType.add(t);
//			if (t.IsGenericType)
//			{
//				JavaGetAllGenericParameterType(t);
//			}
//		}

    }

    private void JavaAddUsing(String usingName) {
        if (CheckInfoUtil.checkNull(usingName)) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0047);
        }
        if (!CheckInfoUtil.checkNull(usingName) && !usingList.contains(usingName)) {
            usingList.add(usingName);
        }
    }

    private String JavaGetClassName(Class type) {
        if (Integer.class == type) {
            return "Integer";
        }
        if (String.class == type) {
            //return "string";
            return "String";
        }
        if (Boolean.class == type) {
            //return "bool";
            return "Boolean";
        }
        if (java.util.Date.class == type) {

            //return "DateTime";
            return "Date";
        }
        if (java.math.BigDecimal.class == type) {
            //return "decimal";
            return "BigDecimal";
        }
        if (Double.class == type) {
            return "Double";
        }
        if (Object.class == type) {
            //return "object";
            return "Object";
        }

        //string fullClassName = type.ToString().Split("`")[0];
        //string[] content = fullClassName.Split(".");
        String fullClassName = type.toString().split("[`]", -1)[0];
        String[] content = fullClassName.split("[.]", -1);
        return content[content.length - 1];


    }

    private String JavaGetGenericExpress(Class type) {
//		if (!type.IsGenericType)
//		{
//			return JavaGetClassName(type);
//		}
//		else
//		{
//			Class[] array = type.GenericTypeArguments;
//			int count = array.length;
//			String info = "{0}";
//			for (int i = 1; i < count; i++)
//			{
//				info = info + "," + "{" + i + "}";
//			}
//			info = JavaGetClassName(type) + "<" + inbfo + ">";
//			String[] arrayStr = new String[count];
//			for (int i = 0; i < count; i++)
//			{
//				arrayStr[i] = JavaGetGenericExpress(array[i]);
//			}
//			info = String.format(info, arrayStr);
//
//			return info;
//		}

        return null;

    }

    private void HandleJavaInfo(IBizParameter para) {
        if (CheckInfoUtil.checkNull(para.getClassName()) && !CheckInfoUtil.checkNull(((BizParameter) para).getNetClassName())) {
            //仅平台提供包，自动转Inspur.Gsp为com.inspur.edp
            if (para.getClassName().startsWith("Inspur.Gsp.")) {
                para.setClassName(HandleJavaClassName(((BizParameter) para).getNetClassName()));
            }
        }
    }

    private String HandleJavaClassName(String source) {
        if (CheckInfoUtil.checkNull(source)) {
            return source;
        }
        String result = "";
        String[] list = source.split("[.]", -1);
        for (int i = 0; i < list.length; i++) {
            String lowerCase = list[i].toLowerCase();
            if (i == 0 && lowerCase.equals("inspur")) {
                result = String.format("%1$s%2$s", result, "com.inspur");
                continue;
            }
            if (i == list.length - 1) {
                // 类名不需要转换为小写
                result = String.format("%1$s%2$s%3$s", result, ".", list[i]);
                continue;
            }
            result = String.format("%1$s%2$s%3$s", result, ".", lowerCase);
        }
        return result;
    }

}